home *** CD-ROM | disk | FTP | other *** search
/ Aminet 28 / Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso / Aminet / util / libs / graphics3d.lha / src / library / graphics3Df.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-17  |  42.9 KB  |  1,795 lines

  1. /*
  2. **      $VER: graphics3Df.c 10.11 (02.03.98)
  3. **
  4. **      Main functions for graphics3D.library
  5. **
  6. **      (C) Copyright 97 Patrizio Biancalani
  7. **      All Rights Reserved.
  8. **      
  9. **    Note: this code is traslate from the blitzbasic 3d graphics engine 
  10. **          V 0.9 of Maciej R. Gorny.
  11. **
  12. */
  13.  
  14. #include <exec/types.h>
  15. #include <exec/memory.h>
  16. #include <proto/exec.h>
  17. #include <proto/intuition.h>
  18. #include <intuition/intuition.h>
  19. #include <intuition/screens.h>
  20.  
  21. #include <graphics/rastport.h>
  22. #include <graphics/clip.h>
  23. #include <graphics/regions.h>
  24. #include <graphics/gfx.h>
  25. #include <graphics/gfxmacros.h>
  26. #include <graphics/layers.h>
  27.  
  28. #include "graphics3Dc.h"
  29. #include "graphics3D.h"
  30. #include "graphics3D2d.h"
  31. #include "graphics3Df_proto.h"
  32. #include "graphics3D2d_proto.h"
  33.  
  34.  /* Please note, that &PovedtBase always resides in register __a6 as well,
  35.     but if we don't need it, we need not reference it here.
  36.  
  37.     Also note, that registers a0, a1, d0, d1 always are scratch registers,
  38.     so you usually should only *pass* parameters there, but make a copy
  39.     directly after entering the function. To avoid problems of kind
  40.     "implementation defined behaviour", you should make a copy of A6 too,
  41.     when it is actually used.
  42.  
  43.     In this example case, scratch register saving would not have been 
  44.     necessary (since there are no other function calls inbetween), but we 
  45.     did it nevertheless.
  46.   */
  47.  
  48. extern void buildlookuptables(struct ambient3d *in);
  49. extern void createworldtocamera(struct ambient3d *in);
  50. extern void recalcobj(struct ambient3d *in);
  51. extern long int t_removeobject(struct ambient3d *in);
  52. extern void localtoworld(struct ambient3d *in);
  53. extern void worldtocamera(struct ambient3d *in);
  54. extern void removebackfacesandshade(struct ambient3d *in);
  55. extern void clipobject3d(struct ambient3d *in);
  56. extern void generatepolylist(struct ambient3d *in);
  57. extern struct objectnode *resetobj(struct ambient3d *in);
  58. extern struct objectnode *nextobj(struct ambient3d *in);
  59. extern struct objectnode *pobj(struct ambient3d *in);
  60. extern void aggobj(struct ambient3d *in);
  61. extern void matidentity4x4(struct matrix4x4 *imatrix); 
  62. extern void matzero4x4(struct matrix4x4 imatrix);
  63. extern void matcopy4x4(struct matrix4x4 *s_m,struct matrix4x4 *d_m);
  64. extern void matmult4x4(struct matrix4x4 *a,struct matrix4x4 *b,
  65.         struct matrix4x4 *r);
  66. extern void matmult4x4s(struct matrix4x4 *a,struct matrix4x4 *b,
  67.         struct matrix4x4 *r);
  68. extern void matmult1x4s(struct matrix1x4 *a,struct matrix4x4 *b,
  69.         struct matrix1x4 *r);
  70. extern void makevector3d(struct vertex *a,struct vertex *b,
  71.          struct vector *result);
  72. extern long int vectormag3d(struct vector *a);
  73. extern void normalpol(struct vertex *v0,struct vertex *v1,
  74.      struct vertex *v2,struct vector *normal);
  75. extern long int dotproduct(struct vector *u,struct vector *v);
  76. extern long int sqri(long int v);
  77. extern long int abs(long int val);
  78. extern void qsort(long int lo0,long int hi0,long int *pol,long int *count);
  79. extern void paintpol(struct ambient3d *in,long int *iwp,
  80.     long int total_polys,long int colb); 
  81. extern long int quicksort(long int len,long int *pol);
  82.  
  83. /**********************************************************/
  84.  
  85. /****************************************************
  86.  ** Routin per la gestione della grafica, in stile **
  87.  ** 2.0                                            ** 
  88.  ** (c) 1994 BIANCA HARD&SOFT Vers:1.00            **
  89.  ****************************************************/
  90.  
  91. /************ FUNZIONI 3D ********************************/
  92.  
  93. /** macro ad uso interno e provvisorio **/
  94. #define mver(val) (val*sizeof(Svertex)+10)
  95. #define mobj(val) (val*sizeof(Sobjectnode)+5)
  96. #define mplf(val) (val*4+5)
  97. #define mtmp(val) (val*sizeof(Spolytemp)+5)
  98. #define tang (361*4+5)
  99. /****************************************/
  100.  
  101. /************************************************
  102.  * apertura e inizializzazione dell'ambiente 3D * 
  103.  * restituisce puntatore ad area generale da    *
  104.  * indicare sempre al richiamo delle altre      *
  105.  * routin.                    *
  106.  ************************************************
  107.  *** INPUT :                    *
  108.  * win  -> puntatore a finestra su cui si vuol  *
  109.  *         operare.                *
  110.  * x0   -> coord. X origine finestra di vis.    *
  111.  * y0   -> coord. Y origine finestra di vis.    *
  112.  * scrw -> larghezza finestra per mondo 3D.     *
  113.  * scrh -> altezza finestra per mondo 3D.       *
  114.  * vdist-> distanza tra osservatore e piano di  *
  115.  *         proiezione.                    *
  116.  *** OUTPUT:                    *
  117.  * puntatore a struttura ambient3d da usarsi in *
  118.  * ingresso di quasi tutte le altre funzioni.   *
  119.  * > 0 allora tutto ok.                *
  120.  * <=0 allora errore, operazione fallita.       * 
  121.  ************************************************/
  122. struct ambient3d *GD_display3d(win,x0,y0,scrw,scrh,vdist)
  123. REG(a0)struct Window *win;
  124. REG(d0)long int x0;
  125. REG(d1)long int y0;
  126. REG(d2)long int scrw;
  127. REG(d3)long int scrh;
  128. REG(d4)long int vdist;
  129. {
  130. long int i;
  131. char *p;
  132. struct ambient3d *ris;
  133. struct vector *vt;
  134. struct dir3d *dan3;
  135. struct Screen *sc;
  136. struct Layer *la;
  137. struct RastPort *rp;
  138.  
  139. #ifdef DEBUG
  140. char dbg[80];
  141. #endif
  142.  
  143. ris=NULL;
  144.  
  145. ris=(struct ambient3d *)AllocMem(sizeof(Sambient3d),NULL);
  146. #ifdef DEBUG
  147. sprintf(dbg,"ambient3d=%ld\n",ris);
  148. write_dbg(dbg);
  149. #endif
  150. if ((long int)ris==NULL)
  151.     {
  152.     GD_close_display3d(ris);
  153.     return(0);
  154.     }
  155.  
  156. /** inizializzo tutti i puntatori a 0 */
  157. ris->graf=0;
  158. ris->temp=0;
  159. ris->iobjects=0;
  160. ris->objects=0;
  161. ris->iwpolys=0;
  162. ris->worldpolys=0;
  163. ris->sintable=0;
  164. ris->costable=0;
  165.  
  166. p=(char *)ini_g(win,5,scrw,scrh);
  167. #ifdef DEBUG
  168. sprintf(dbg,"ini_g=%ld\n",p);
  169. write_dbg(dbg);
  170. #endif
  171. if (p==(char *)NULL)
  172.     {
  173.     GD_close_display3d(ris);
  174.     return(0);
  175.     }
  176. ris->graf=(struct grafica *)p;
  177.  
  178. p=(char *)AllocMem(mver(MAXVERT),NULL);
  179. if (p==(char *)NULL)
  180.     {
  181.     GD_close_display3d(ris);
  182.     return(0);
  183.     }
  184. ris->temp=p;
  185.  
  186. p=(char *)AllocMem(mobj(MAXOBJECT),NULL);
  187. if (p==(char *)NULL)
  188.     {
  189.     GD_close_display3d(ris);
  190.     return(0);
  191.     }
  192. ris->objects=(struct objectnode *)p;
  193.  
  194. p=(char *)AllocMem(mplf(MAXPLFRAM),NULL);
  195. if (p==(char *)NULL)
  196.     {
  197.     GD_close_display3d(ris);
  198.     return(0);
  199.     }
  200. ris->iwpolys=(long int *)p;
  201.  
  202. p=(char *)AllocMem(mtmp(MAXPLFRAM),NULL);
  203. if (p==(char *)NULL)
  204.     {
  205.     GD_close_display3d(ris);
  206.     return(0);
  207.     }
  208. ris->worldpolys=(struct polytemp *)p;
  209.  
  210. p=(char *)AllocMem(tang,NULL);
  211. #ifdef DEBUG
  212. sprintf(dbg,"sintable=%ld\n",p);
  213. write_dbg(dbg);
  214. #endif
  215. if (p==(char *)NULL)
  216.     {
  217.     GD_close_display3d(ris);
  218.     return(0);
  219.     }
  220. ris->sintable=(long int *)p;
  221.  
  222. p=(char *)AllocMem(tang,NULL);
  223. #ifdef DEBUG
  224. sprintf(dbg,"costable=%ld\n",p);
  225. write_dbg(dbg);
  226. #endif
  227. if (p==(char *)NULL)
  228.     {
  229.     GD_close_display3d(ris);
  230.     return(0);
  231.     }
  232. ris->costable=(long int *)p;
  233.  
  234. /** inizializzo tutte le variabili **/
  235. ris->win=win;
  236. ris->half_screen_width=(ris->graf->clipdx)/2;
  237. ris->half_screen_height=(ris->graf->clipdy)/2;
  238. ris->zoom=FIXV;
  239. ris->aspect_ratio=1*FIXV;
  240. ris->inv_aspect_ratio=1*FIXV;
  241. ris->viewing_distance=vdist;
  242. ris->minx=x0;
  243. ris->miny=y0;
  244. ris->maxx=ris->graf->clipdx;
  245. ris->maxy=ris->graf->clipdy;
  246. ris->agg_all=1;
  247. ris->gl_triangle_color=1;
  248. ris->gcolor=0;
  249. ris->ambient_light=1*FIXV;
  250. ris->projection_type=PROSP_P;
  251. vt=&ris->light_source;
  252.  
  253. vt->x=234;     /* =INT(0.913913*FIXV) */
  254. vt->y=100;     /* =INT(0.389759*FIXV) */
  255. vt->z=-29;     /* =INT(-0.113369*FIXV)*/
  256. vt->w=0;
  257.  
  258. /*
  259. vt->x=1*FIXV;
  260. vt->y=-2*FIXV;
  261. vt->z=5*FIXV;
  262. vt->w=0*FIXV;
  263. */
  264. vt=&ris->view_point;
  265. vt->x=1*FIXV;
  266. vt->y=2*FIXV;
  267. vt->z=3*FIXV;
  268. vt->w=10*FIXV;
  269. dan3=&ris->view_angle;
  270. dan3->angx=0;
  271. dan3->angy=0;
  272. dan3->angz=0;
  273. ris->near_z=ris->viewing_distance;
  274. ris->far_z=4096;
  275. ris->bord_col=1;
  276. ris->clip_mode=ZPLANE;
  277. ris->view_mode=SOLID;
  278. ris->maxintensity=0;
  279. ris->total_polys=0;
  280. ris->total_objects=0;
  281. ris->attuale=0;
  282. ris->numero=1;
  283.  
  284. /* installo una clipregion, per effettuare il clip automatico */
  285. i=clipbox(ris->graf,ris->minx,ris->miny,ris->maxx,ris->maxy);
  286. #ifdef DEBUG
  287. sprintf(dbg,"clipbox esi=%ld\n",i);
  288. write_dbg(dbg);
  289. #endif
  290. if (i==NULL)
  291.     {
  292.     GD_close_display3d(ris);
  293.     return(0);
  294.     }    
  295.  
  296. /** inizializzo tabelle seno e coseno **/
  297. buildlookuptables(ris);
  298.  
  299. return(ris);
  300.  
  301. }
  302.  
  303. /************************************************
  304.  * chiusura ed eliminazione dell'ambiente 3D    * 
  305.  ************************************************
  306.  *** INPUT :                    *
  307.  * in -> valore >0 restituito da display3d.     *
  308.  *** OUTPUT:                    *
  309.  * nessuno.                    *
  310.  ************************************************/
  311. void GD_close_display3d(in)
  312. REG(a0)struct ambient3d *in;
  313. {
  314. long int i,n;
  315.  
  316. if (in==NULL) return(0);
  317.  
  318. if (in->total_objects>NULL)
  319.     {
  320.     n=in->total_objects;
  321.     for(i=0 ; i<n ; i++)
  322.         {
  323.         in->attuale=0;    
  324.         GD_deleteobject(in);
  325.         }
  326.     }
  327. if (in->temp!=NULL) FreeMem(in->temp,mver(MAXVERT));
  328. if (in->sintable!=NULL) FreeMem(in->sintable,tang);
  329. if (in->costable!=NULL) FreeMem(in->costable,tang);
  330. if (in->iwpolys!=NULL) FreeMem(in->iwpolys,mplf(MAXPLFRAM));
  331. if (in->worldpolys!=NULL) FreeMem(in->worldpolys,mtmp(MAXPLFRAM));
  332. if (in->iobjects!=NULL) FreeMem(in->iobjects,NULL);
  333. if (in->objects!=NULL) FreeMem(in->objects,mobj(MAXOBJECT));
  334. if (in->graf!=NULL) close_g(in->graf);
  335.     
  336. FreeMem(in,sizeof(Sambient3d));
  337.  
  338. }
  339.  
  340. /********************************************
  341.  ** cambia il modo di visualizzazione      **
  342.  ** globale.                   **
  343.  ********************************************
  344.  *** INPUT :                    *
  345.  * in  -> valore >0 restituito da display3d.*
  346.  * modo-> modalita' di visualizzazione      *
  347.  *        oggetti.                *
  348.  *        WIREF= wire frame                 *
  349.  *        SOLID= solid shade               *
  350.  *        FLAT = flat shading            *
  351.  * b_col-> colore bordo, se <0 allora nessun*
  352.  *        bordo per i poligoni.            *
  353.  *** OUTPUT:                     *
  354.  * >0 tutto ok.                    *
  355.  * =0 valore non valido.            *
  356.  ********************************************/
  357. long int GD_changeviewmode(in,modo,b_col)
  358. REG(a0)struct ambient3d *in;
  359. REG(d0)long int modo;
  360. REG(d1)long int b_col;
  361. {
  362. struct objectnode *obj;
  363. long int buf;
  364.  
  365. in->bord_col=b_col;
  366.  
  367. if (modo!=WIREF AND modo!=SOLID AND modo!=FLAT) return(0);
  368.  
  369. buf=in->attuale;
  370. obj=resetobj(in);
  371. while(obj!=NULL)
  372.     {
  373.     obj->shade=modo;
  374.     obj->trasf|=0x01;
  375.     obj=nextobj(in);
  376.     }
  377.  
  378. in->view_mode=modo;
  379. in->attuale=buf;
  380.  
  381. return(1);
  382. }
  383.  
  384. /********************************************
  385.  ** cambia il modo di visualizzazione      **
  386.  ** dell'oggetto attualmente selezionato.  **
  387.  ********************************************
  388.  *** INPUT :                    *
  389.  * in  -> valore >0 restituito da display3d.*
  390.  * modo-> modalita' di visualizzazione      *
  391.  *        oggetti.                *
  392.  *        WIREF= wire frame                 *
  393.  *        SOLID= solid shade               *
  394.  *        FLAT = flat shading            *
  395.  *** OUTPUT:                     *
  396.  * >0 tutto ok.                    *
  397.  * =0 valore non valido.            *
  398.  ********************************************/
  399. long int GD_changeviewmodeobj(in,modo)
  400. REG(a0)struct ambient3d *in;
  401. REG(d0)long int modo;
  402. {
  403. struct objectnode *obj;
  404.  
  405. if (modo!=WIREF AND modo!=SOLID AND modo!=FLAT) return(0);
  406.  
  407. obj=pobj(in);
  408.  
  409. obj->shade=modo;
  410. obj->trasf|=0x01;
  411.  
  412. return(1);
  413. }
  414.  
  415. /**********************************************
  416.  ** crea una palette sfumata tra due colori  **
  417.  ** nella palette dello schermo, in modo di  **
  418.  ** poter poi usare il FLAT SHADING.         **
  419.  **********************************************
  420.  *** INPUT :                      * 
  421.  * in -> valore > 0 restituito da display3d.  *
  422.  * fr -> n# primo registro colore da settare. *
  423.  * lr -> n# ultimo reg. colore da settare.    *
  424.  * init_color -> punt. a struttura rgbtype    *
  425.  *               con valore rgb iniz. colore. *
  426.  * last_color -> punt. a struttura rgbtype    *
  427.  *         con valore rgb fin. color.   *
  428.  *** OUTPUT:                      *
  429.  * nessuno.                      *
  430.  **********************************************/
  431. void GD_touchpalette(in,fr,lr,init_color,last_color)
  432. REG(a0)struct ambient3d *in;
  433. REG(d0)long int fr;
  434. REG(d1)long int lr;
  435. REG(a1)struct rgbtype *init_color;
  436. REG(a2)struct rgbtype *last_color;
  437. {
  438. long int m,t,i,fc,lc;
  439. long int *temp_red,*temp_green,*temp_blue,*temp;
  440.  
  441. temp=AllocMem(900*sizeof(long int),NULL);
  442. if ((long int)temp>NULL)
  443.     {
  444.     temp_red=&temp[0];
  445.     temp_green=&temp[300];
  446.     temp_blue=&temp[600];
  447.  
  448.     m=lr-fr-1;
  449.     if (in->maxintensity<m OR in->maxintensity==NULL) 
  450.             in->maxintensity=m;
  451.  
  452.     lc=last_color->r;
  453.     fc=init_color->r;
  454.     t=(lc-fc)/(lr-fr);
  455.     for(i=fr ;i<=lr ;i++) temp_red[i-fr]=fc+t*(i-fr);
  456.     
  457.     lc=last_color->g;
  458.     fc=init_color->g;
  459.     t=(lc-fc)/(lr-fr);
  460.     for(i=fr ;i<=lr ;i++) temp_green[i-fr]=fc+t*(i-fr);
  461.  
  462.     lc=last_color->b;
  463.     fc=init_color->b;
  464.     t=(lc-fc)/(lr-fr);
  465.     for(i=fr ;i<=lr ;i++) temp_blue[i-fr]=fc+t*(i-fr);
  466.  
  467.     for(i=0 ;i<lr-fr+1 ;i++)
  468.        GD_rgb4(in,i+fr,temp_red[i],temp_green[i],temp_blue[i]);
  469.  
  470.     FreeMem(temp,900*sizeof(long int));    
  471.     }
  472.  
  473. }
  474.  
  475. /**********************************************
  476.  ** muove l'osservatore di dist unita'       **
  477.  **********************************************
  478.  *** INPUT :                      * 
  479.  * in -> valore > 0 restituito da display3d.  *
  480.  * dist -> numero di unita' di spostamento.   *
  481.  *         (il valore deve essere FIXPOINT)   *
  482.  *** OUTPUT:                      *
  483.  * nessuno.                      *
  484.  **********************************************/
  485. void GD_moveforward(in,dist)
  486. REG(a0)struct ambient3d *in;
  487. REG(d0)long int dist;
  488. {
  489. long int *sin,*cos;
  490. struct dir3d *vang;
  491. struct vector *vp;
  492. long int active_axes,dx,dy,dz;
  493.  
  494. sin=in->sintable;
  495. cos=in->costable;
  496. vang=&in->view_angle;
  497. vp=&in->view_point;
  498.  
  499. active_axes=0;
  500.  
  501. if (vang->angx!=NULL) active_axes+=1;
  502. if (vang->angy!=NULL) active_axes+=2;
  503. if (vang->angz!=NULL) active_axes+=4;
  504.  
  505. switch (active_axes)
  506.     {
  507.     case (0):
  508.         dx=0;
  509.         dy=0;
  510.         dz=dist;
  511.         break;
  512.     case (1):
  513.         dx=0;
  514.         dy=(dist*cos[vang->angx]) >> SFIXV;
  515.         dz=(dist*sin[vang->angx]) >> SFIXV;
  516.         break;
  517.     case (2):
  518.         dx=(dist*sin[vang->angy]) >> SFIXV;
  519.         dy=0;
  520.         dz=(dist*cos[vang->angy]) >> SFIXV;
  521.         break;
  522.     case (3):
  523.         dx=(dist*sin[vang->angy]) >> SFIXV;
  524.         dy=(dist*cos[vang->angx]) >> SFIXV;
  525.         dz=(dist*cos[vang->angy]) >> SFIXV + 
  526.             (dist*sin[vang->angx]) >> SFIXV;
  527.         break;
  528.     case (4):        
  529.         dx=(dist*sin[vang->angz]) >> SFIXV;
  530.         dy=(dist*cos[vang->angz]) >> SFIXV;
  531.         dz=0;
  532.         break;        
  533.     case (5):
  534.         dx=(dist*sin[vang->angz]) >> SFIXV;
  535.         dy=(dist*cos[vang->angx]) >> SFIXV +
  536.             (dist*cos[vang->angz]) >> SFIXV;    
  537.         dz=(dist*sin[vang->angx]) >> SFIXV;
  538.         break;
  539.  
  540.     case (6):
  541.         dx=(dist*sin[vang->angy]) >> SFIXV +
  542.             (dist*sin[vang->angz]) >> SFIXV;
  543.         dy=(dist*cos[vang->angz]) >> SFIXV;
  544.         dz=(dist*cos[vang->angy]) >> SFIXV;
  545.         break;
  546.  
  547.     case (7):
  548.         dx=(dist*sin[vang->angy]) >> SFIXV +
  549.             (dist*sin[vang->angz]) >> SFIXV;    
  550.         dy=(dist*cos[vang->angx]) >> SFIXV +
  551.             (dist*cos[vang->angz]) >> SFIXV;    
  552.         dz=(dist*sin[vang->angx]) >> SFIXV +
  553.             (dist*cos[vang->angy]) >> SFIXV;
  554.         break;    
  555.  
  556.     }
  557.  
  558. vp->x+=dx;
  559. vp->y+=dy;
  560. vp->z+=dz;
  561.  
  562. /* forzo aggiornamento di TUTTA la scena */
  563. in->agg_all=1;
  564.  
  565. }
  566.  
  567. /**********************************************
  568.  ** cambio l'angolo della visuale            **
  569.  **********************************************
  570.  *** INPUT :                      * 
  571.  * in -> valore > 0 restituito da display3d.  *
  572.  * ax -> valore rotazione su asse x.          *
  573.  *       (in gradi e intero)              *
  574.  * ay -> valore rotazione su asse y.          *
  575.  *       (in gradi e intero)              *
  576.  * az -> valore rotazione su asse z.          *
  577.  *       (in gradi e intero)              *
  578.  *** OUTPUT:                      *
  579.  * nessuno.                      *
  580.  **********************************************/
  581. void GD_viewangle(in,ax,ay,az)
  582. REG(a0)struct ambient3d *in;
  583. REG(d0)long int ax;
  584. REG(d1)long int ay;
  585. REG(d2)long int az;
  586. {
  587. struct dir3d *va;
  588. long int ta;
  589.  
  590. va=&in->view_angle;
  591.  
  592. if (ax<0 OR ax>360)
  593.     {
  594.     ta=ax/360;
  595.     ax-=ta*360;
  596.     if (ax<0) ax+=360;
  597.     }
  598.  
  599. if (ay<0 OR ay>360)
  600.     {
  601.     ta=ay/360;
  602.     ay-=ta*360;
  603.     if (ay<0) ay+=360;
  604.     }
  605.  
  606. if (az<0 OR az>360)
  607.     {
  608.     ta=az/360;
  609.     az-=ta*360;
  610.     if (az<0) az+=360;
  611.     }
  612.  
  613. va->angx=ax;
  614. va->angy=ay;
  615. va->angz=az;
  616.  
  617. /* forzo aggiornamento di TUTTA la scena */
  618. in->agg_all=1;
  619.  
  620. }
  621.  
  622. /******************************************************
  623.  ** setta i piani near e far del volume visualizzato **
  624.  ******************************************************
  625.  *** INPUT :                          * 
  626.  * in   -> valore > 0 restituito da display3d.          *
  627.  * near -> posizione piano vicino.(valore intero)     *
  628.  * far  -> posizione piano lontano.(valore intero)    *
  629.  *** OUTPUT:                          *
  630.  * nessuno.                          *
  631.  ******************************************************/
  632. void GD_frustum(in,near,far)
  633. REG(a0)struct ambient3d *in;
  634. REG(d0)long int near;
  635. REG(d1)long int far;
  636. {
  637. long int n,f;
  638. /* i valori in input devono essere interi */
  639. n=near;
  640. f=far;
  641. if (near<in->viewing_distance) n=in->viewing_distance;
  642. if (far<near) f=2*n;
  643.  
  644. in->near_z=n;
  645. in->far_z=f;
  646.  
  647. }
  648.  
  649. /******************************************************
  650.  ** crea e posiziona una sorgente di luce .          **
  651.  ******************************************************
  652.  *** INPUT :                          * 
  653.  * in -> valore > 0 restituito da display3d.          *
  654.  * x  -> valore coordinata X luce(valore FIXPOINT).   *
  655.  * y  -> valore coordinata Y luce(valore FIXPOINT).   *
  656.  * z  -> valore coordinata Z luce(valore FIXPOINT).   *
  657.  *** OUTPUT:                          *
  658.  * nessuno.                          *
  659.  ******************************************************/
  660. void GD_createlightsource(in,x,y,z)
  661. REG(a0)struct ambient3d *in;
  662. REG(d0)long int x;
  663. REG(d1)long int y;
  664. REG(d2)long int z;
  665. {
  666. struct vertex v1,v2;
  667.  
  668. /* i valori in ingresso devono gia' essere in fixpoint */
  669. v1.x=x;
  670. v1.y=y;
  671. v1.z=z;
  672. v2.x=0;
  673. v2.y=0;
  674. v2.z=0;
  675.  
  676. makevector3d(&v1,&v2,&in->light_source);
  677.  
  678. /* forzo aggiornamento scena */
  679. in->agg_all=1;
  680.  
  681. }
  682.  
  683. /**********************************************
  684.  ** setta l'intensita' di luce ambientale.   **
  685.  **********************************************
  686.  *** INPUT :                      * 
  687.  * in  -> valore > 0 restituito da display3d. *
  688.  * inte-> valore intensita' luce          *
  689.  *       (valore in FIXPOINT).              *
  690.  *** OUTPUT:                      *
  691.  * nessuno.                      *
  692.  **********************************************/
  693. void GD_ambientlight(in,inte)
  694. REG(a0)struct ambient3d *in;
  695. REG(d0)long int inte;
  696. {
  697.  
  698. /* il valore di input deve essere in fixpoint */
  699. in->ambient_light=inte;
  700.  
  701. if (inte>>SFIXV > in->maxintensity) inte=in->maxintensity<<SFIXV;
  702. if (inte<NULL) inte=0;
  703.  
  704. /* forzo aggiornamento scena */
  705. in->agg_all=1;
  706.  
  707. }
  708.  
  709. /************************************************
  710.  ** posiziona il punto di vista nel mondo 3d.  ** 
  711.  ************************************************
  712.  *** INPUT :                        * 
  713.  * in -> valore > 0 restituito da display3d.    *
  714.  * x  -> valore coordinata X camera        *
  715.  *     (valore FIXPOINT).                 *
  716.  * y  -> valore coordinata Y camera        *
  717.  *       (valore FIXPOINT).               *
  718.  * z  -> valore coordinata Z camera        *
  719.  *       (valore FIXPOINT).               *
  720.  *** OUTPUT:                    *
  721.  * nessuno.                    *
  722.  ************************************************/
  723. void GD_positioncamera(in,x,y,z)
  724. REG(a0)struct ambient3d *in;
  725. REG(d0)long int x;
  726. REG(d1)long int y;
  727. REG(d2)long int z; 
  728. {
  729.  
  730. /* i valori in input devono gia' essere in fixpoint */ 
  731. in->view_point.x=x;
  732. in->view_point.y=y;
  733. in->view_point.z=z;
  734.  
  735. /* forzo aggiornamento scena */
  736. in->agg_all=1;
  737.  
  738. }
  739.  
  740. /************************************************
  741.  ** variazione aspect ratio scena.            **
  742.  ************************************************
  743.  *** INPUT :                        * 
  744.  * in -> valore > 0 restituito da display3d.    *
  745.  * ratio-> nuovo aspect ratio.(valore FIPOINT). *
  746.  *** OUTPUT:                    *
  747.  * nessuno.                    *
  748.  ************************************************/
  749. void GD_aspectratio(in,ratio)
  750. REG(a0)struct ambient3d *in;
  751. REG(d0)long int ratio;
  752. {
  753.  
  754. in->aspect_ratio=ratio;
  755. in->inv_aspect_ratio=FIXV*FIXV/ratio;
  756.  
  757. }
  758.  
  759. /************************************************
  760.  ** setta un particolare modo per il clipping. **
  761.  ************************************************
  762.  *** INPUT :                        * 
  763.  * in -> valore > 0 restituito da display3d.    *
  764.  * mode -> nuovo modo di clipping.        *
  765.  *         (ZPLANE ,FRUSTUM).            *
  766.  *** OUTPUT:                    *
  767.  * nessuno.                    *
  768.  ************************************************/
  769. void GD_clipmode(in,mode)
  770. REG(a0)struct ambient3d *in;
  771. REG(d0)long int mode;
  772. {
  773.  
  774. in->clip_mode=mode;
  775. if (mode!=FRUSTUM AND mode!=ZPLANE) in->clip_mode=ZPLANE;
  776.  
  777. }
  778.  
  779. /************************************************
  780.  ** trova l'oggetto e il poligono al cui       **
  781.  ** interno risiede il punto dato.           **
  782.  ************************************************
  783.  *** INPUT :                        *
  784.  * in -> valore > 0 restituito da display3d.    *
  785.  * np -> puntatore a long, dove mettere n# pol. *
  786.  *       al cui interno risiede il punto.    *
  787.  * xp -> coordinata x punto dato nella finestra * 
  788.  *     in cui e' visualizzata la scena.    *
  789.  *     (valore intero).            *  
  790.  * yp -> coordinata y punto dato nella finestra * 
  791.  *     in cui e' visualizzata la scena.    *
  792.  *     (valore intero).            *  
  793.  *** OUTPUT:                    *
  794.  * = 0 nessun oggetto trovato.            *
  795.  *     (in questo caso valore in np senza sign.)*
  796.  * > 0 valore identificativo oggetto trovato.   *
  797.  *** NOTA:                    *
  798.  * L'algoritmo che ho usato sembra funzioni ma  *
  799.  * e' stato trovato in modo del tutto empirico  *
  800.  * se qualcuno mi sa spiegare perche' funzioni  *
  801.  * e' il benvenuto.                *
  802.  ************************************************/
  803. long int GD_pickobj(in,np,xp,yp)
  804. REG(a0)struct ambient3d *in;
  805. REG(a1)long int *np;
  806. REG(d0)long int xp;
  807. REG(d1)long int yp;
  808. {
  809. struct polytemp *plt;
  810. long int *ip,id,i,ris;
  811. long int x,y,xm,ym,x1,x2,x3,y1,y2,y3;
  812.  
  813. ip=in->iwpolys;
  814. ris=0;
  815. i=in->total_polys-1;
  816.  
  817. #ifdef OPTG
  818. x=xp-in->minx;
  819. y=yp-in->miny;
  820. #else
  821. x=xp;
  822. y=yp;
  823. #endif
  824.  
  825. while ((i>=0 AND ris==0))
  826.     {
  827.     plt=(struct polytemp *)ip[i];
  828. /* traslo origini poligono su punto dato */
  829.     x1=plt->x1-x;
  830.     y1=plt->y1-y; 
  831.     x2=plt->x2-x;
  832.     y2=plt->y2-y; 
  833.     x3=plt->x3-x;
  834.     y3=plt->y3-y; 
  835. /* calcolo massimo x e y del triangolo (in valore assoluto)*/ 
  836.     xm=abs(x1);
  837.     if (abs(x2)>xm) xm=abs(x2);
  838.     if (abs(x3)>xm) xm=abs(x3);
  839.     ym=abs(y1);
  840.     if (abs(y2)>ym) ym=abs(y2);
  841.     if (abs(y3)>ym) ym=abs(y3);
  842. /* sommo gli assi dei tre vertici tra loro */
  843.     x1=abs(x1+x2+x3);
  844.     y1=abs(y1+y2+y3);
  845. /* test se risultato in valore assoluto maggiore dei val. massimi per x e y*/
  846. /* se no, punto interno altrimenti esterno */        
  847.     if (x1<=xm AND y1<=ym) 
  848.         {
  849.         ris=plt->obj;
  850.         np[0]=plt->npol;
  851.         }
  852. /* se poligono composto di 4 lati ripeto il test per l'altro triangolo */
  853.     if (plt->numpoints=4)
  854.         {
  855.     /* traslo origini poligono su punto dato */
  856.         x1=plt->x3-x;
  857.         y1=plt->y3-y; 
  858.         x2=plt->x4-x;
  859.         y2=plt->y4-y; 
  860.         x3=plt->x1-x;
  861.         y3=plt->y1-y; 
  862.         xm=abs(x1);
  863.         if (abs(x2)>xm) xm=abs(x2);
  864.         if (abs(x3)>xm) xm=abs(x3);
  865.         ym=abs(y1);
  866.         if (abs(y2)>ym) ym=abs(y2);
  867.         if (abs(y3)>ym) ym=abs(y3);
  868.         x1=abs(x1+x2+x3);
  869.         y1=abs(y1+y2+y3);
  870.         if (x1<=xm AND y1<=ym) 
  871.             {
  872.             ris=plt->obj;
  873.             np[0]=plt->npol;
  874.             }
  875.         }
  876.     i--;    
  877.     }
  878.  
  879. return(ris);
  880.  
  881. }
  882.  
  883. /************************************************
  884.  ** crea e inizializza una nuova struttura     **
  885.  ** oggetto e tutte le sue sottostrutture.     **
  886.  ** Lo fa diventare l'attuale.               **
  887.  ************************************************
  888.  *** INPUT :                        * 
  889.  * in -> valore > 0 restituito da display3d.    *
  890.  * name -> puntatore a stringa con nome oggetto.*
  891.  * pol  -> n# totale poligoni nell'oggetto.     *
  892.  * vert -> n# totale vertici nell'oggetto.      *
  893.  *** OUTPUT:                    *
  894.  * > 0 tutto ok, rende n# identificatore oggetto*
  895.  * =0 errore, operazione fallita.        * 
  896.  ************************************************/
  897. long int GD_newobj(in,name,pol,vert)
  898. REG(a0)struct ambient3d *in;
  899. REG(a1)char *name;
  900. REG(d0)long int pol;
  901. REG(d1)long int vert;
  902. {
  903. long int i,id,lv;
  904. struct objectnode *ob;
  905. char *n;
  906.  
  907. id=in->total_objects;
  908. if (id>MAXOBJECT) return(0);
  909. if (vert>MAXVERT) return(0);
  910.  
  911. in->total_objects+=1;
  912.  
  913. in->attuale=id;
  914. ob=pobj(in);
  915.  
  916. n=ob->name;
  917.  
  918. i=0;
  919. while(i<21 OR name[i]!=0x00) n[i]=name[i++];
  920. n[i]=0x00;
  921.  
  922. /** inizializzo valori di default */
  923. ob->numpolys=pol;
  924. ob->numverts=vert;
  925. ob->vorig=0;
  926. ob->vlocal=0;
  927. ob->vcamera=0;
  928. ob->polys=0;
  929. ob->state=1;
  930. ob->shade=in->view_mode;
  931. ob->trasf=1;
  932.  
  933. /* definisco origine oggetto alle coordinate 0,0,0 */
  934. ob->worldposx=0;
  935. ob->worldposy=0;
  936. ob->worldposz=0;
  937.  
  938. lv=vert*sizeof(Svertex);
  939.  
  940. n=(char *)AllocMem(lv,NULL);
  941. if (n<=(char *)NULL)
  942.     {
  943.     GD_deleteobject(in);
  944.     return(0);
  945.     }
  946. ob->vorig=(struct vertex *)n;
  947.  
  948. n=(char *)AllocMem(lv,NULL);
  949. if (n<=(char *)NULL)
  950.     {
  951.     GD_deleteobject(in);
  952.     return(0);
  953.     }
  954. ob->vlocal=(struct vertex *)n;
  955.  
  956. n=(char *)AllocMem(lv,NULL);
  957. if (n<=(char *)NULL)
  958.     {
  959.     GD_deleteobject(in);
  960.     return(0);
  961.     }
  962. ob->vcamera=(struct vertex *)n;
  963.  
  964. n=(char *)AllocMem(pol*sizeof(Spolygon),NULL);
  965. if (n<=(char *)NULL)
  966.     {
  967.     GD_deleteobject(in);
  968.     return(0);
  969.     }
  970. ob->polys=(struct polygon *)n;
  971.  
  972. ob->id=in->numero;
  973. in->numero+=1;
  974.  
  975. return(ob->id);
  976.  
  977. }
  978.  
  979. /************************************************
  980.  ** elimina oggetto attuale e libera la memoria**
  981.  ************************************************
  982.  *** INPUT :                        * 
  983.  * in -> valore > 0 restituito da display3d.    *
  984.  *** OUTPUT:                    *
  985.  * nessuno.                    *
  986.  ************************************************/
  987. void GD_deleteobject(in)
  988. REG(a0)struct ambient3d *in;
  989. {
  990. struct objectnode *ob;
  991. char *s,*d;
  992. long int sob,i;
  993.  
  994. if (in->total_objects==NULL) return(0);
  995.  
  996. sob=sizeof(Sobjectnode);
  997. ob=pobj(in);
  998.  
  999. i=sizeof(Svertex)*ob->numverts;
  1000.  
  1001. if (ob->vorig!=NULL) FreeMem(ob->vorig,i);
  1002. if (ob->vlocal!=NULL) FreeMem(ob->vlocal,i);
  1003. if (ob->vcamera!=NULL) FreeMem(ob->vcamera,i);
  1004. if (ob->polys!=NULL) FreeMem(ob->polys,sizeof(Spolygon)*ob->numpolys);
  1005.  
  1006. in->total_objects-=1;
  1007. if (in->attuale>=in->total_objects)
  1008.     {
  1009.     in->attuale=in->total_objects-1;
  1010.     return(0);
  1011.     }
  1012.  
  1013. /* elimino i dati dell'oggetto */
  1014. /*cmem(ob+sob,ob,mul(in.total_objects-in.attuale-1,sob))*/
  1015. /** !!!attenzione!!! questa routin in questo caso e' ok ***/
  1016. /** ma se si devono spostare aree sovrapposte non va piu' bene **/ 
  1017. d=(char *)ob;
  1018. s=(char *)ob+sob;
  1019. for(i=0 ; i<(in->total_objects-in->attuale)*sob ; i++) d[i]=s[i];
  1020.  
  1021. }
  1022.  
  1023. /************************************************
  1024.  ** inserisce un vertice nell'oggetto corrente.**
  1025.  ************************************************
  1026.  *** INPUT :                        * 
  1027.  * in -> valore > 0 restituito da display3d.    *
  1028.  * num -> numero indice del vertice da inserire *
  1029.  *        (#1 = 0, #2 = 1, ...).         *
  1030.  * x   -> valore coordinata x vertice           *
  1031.  *        (in FIXPOINT)                *
  1032.  * y   -> valore coordinata y vertice           *
  1033.  *        (in FIXPOINT)                *
  1034.  * z   -> valore coordinata z vertice           *
  1035.  *        (in FIXPOINT)                *
  1036.  *** OUTPUT:                    *
  1037.  * > 0 tutto ok, vertice inserito.        *
  1038.  * = 0 operazione fallita.            *
  1039.  *** NOTA  :                    *
  1040.  * Se si cerca di inserire un vertice con indice*
  1041.  * maggiore del numero di vertici definiti per  *
  1042.  * l'oggetto l'operazione fallira'.        *
  1043.  ************************************************/
  1044. long int GD_addobjvertex(in,num,x,y,z)
  1045. REG(a0)struct ambient3d *in;
  1046. REG(d0)long int num;
  1047. REG(d1)long int x;
  1048. REG(d2)long int y;
  1049. REG(d3)long int z;
  1050. {
  1051. struct objectnode *obj;
  1052. struct vertex *vl,*vo;
  1053.  
  1054. obj=pobj(in);
  1055.  
  1056. vl=obj->vlocal;
  1057. vo=obj->vorig;
  1058.  
  1059. if (num+1>obj->numverts) return(0);
  1060. if (num<NULL) return(0);
  1061.  
  1062. vl[num].x=x;
  1063. vo[num].x=x;
  1064. vl[num].y=y;
  1065. vo[num].y=y;
  1066. vl[num].z=z;
  1067. vo[num].z=z;
  1068.  
  1069. return(1);
  1070. }
  1071.  
  1072. /************************************************
  1073.  ** inserisce un poligono all'oggetto corrente **
  1074.  ** se p4=-1 allora poligono a 3 vertici.      **
  1075.  ************************************************
  1076.  *** INPUT :                        * 
  1077.  * in -> valore > 0 restituito da display3d.    *
  1078.  * num -> numero indice del poligono da inserire*
  1079.  *        (#1 = 0, #2 = 1, ...).        *
  1080.  * p1  -> numero indice primo punto pol. su     *
  1081.  *        elenco vertico oggetto.        *
  1082.  * p2  -> numero indice secondo punto pol. su   *
  1083.  *        elenco vertico oggetto.        *
  1084.  *        (=-1 allora poligono a un vertice).   *
  1085.  * p3  -> numero indice terzo punto pol. su     *
  1086.  *        elenco vertico oggetto.        *
  1087.  *        (=-1 allora poligono a due vertici).  *
  1088.  * p4  -> numero indice quarto punto pol. su    *
  1089.  *        elenco vertico oggetto .        *
  1090.  *        (=-1 allora poligono a tre vertici).  *
  1091.  *** OUTPUT:                    *
  1092.  * > 0 tutto ok, poligono inserito.        *
  1093.  * = 0 operazione fallita.            *
  1094.  *** NOTA  :                    *
  1095.  * Se si cerca di inserire un poligono con      *
  1096.  * indice maggiore del numero di poligoni       *
  1097.  * definiti per l'oggetto l'operazione fallira'.*
  1098.  ************************************************/
  1099. long int GD_addobjpoly(in,num,p1,p2,p3,p4)
  1100. REG(a0)struct ambient3d *in;
  1101. REG(d0)long int num;
  1102. REG(d1)long int p1;
  1103. REG(d2)long int p2;
  1104. REG(d3)long int p3;
  1105. REG(d4)long int p4;
  1106. {
  1107. struct objectnode *obj;
  1108. struct polygon *poly;
  1109. struct vertex *vert;
  1110. long int t;
  1111.  
  1112. obj=pobj(in);
  1113. poly=obj->polys;
  1114. vert=obj->vorig;
  1115.  
  1116. if (num+1>obj->numpolys) return(0);
  1117. if (num<NULL) return(0);
  1118.  
  1119. t=1;
  1120. if (p1<NULL) return(0);
  1121. if (p2>=NULL) t++;
  1122. if (p3>=NULL) t++;
  1123. if (p4>=NULL) t++;
  1124.  
  1125. poly[num].numpoints=t;
  1126. poly[num].twosided=1;      /* default poligono a due facce */
  1127. poly[num].visible=1;
  1128. poly[num].clipped=0;
  1129. poly[num].active=1;
  1130. poly[num].vertexlist0=p1;
  1131. if (t>1) poly[num].vertexlist1=p2;
  1132. if (t>2) poly[num].vertexlist2=p3;
  1133. if (t>3) poly[num].vertexlist3=p4;
  1134.  
  1135. return(1);
  1136. }
  1137.  
  1138. /************************************************
  1139.  ** cambia le caratteristiche di un poligono.  **
  1140.  ************************************************
  1141.  *** INPUT :                        * 
  1142.  * in -> valore > 0 restituito da display3d.    *
  1143.  * num -> numero indice del poligono da variare *
  1144.  *        (#1 = 0, #2 = 1, ...).        *
  1145.  * color -> colore base per oggetto, in caso di *
  1146.  *          visualizzazione flat usera i colori *
  1147.  *          successivi a questo per sfumare.    *
  1148.  * twoside -> indica se poligono a 2 facce (1) o*
  1149.  *            a una faccia (0).            *
  1150.  *            Se a due facce sara' visibile solo*
  1151.  *          la faccia frontale.        *
  1152.  *** OUTPUT:                    *
  1153.  * > 0 tutto ok, poligono modificato.        *
  1154.  * = 0 operazione fallita.            *
  1155.  *** NOTA  :                    *
  1156.  * Se si cerca di modificare un poligono con    *
  1157.  * indice maggiore del numero di poligoni       *
  1158.  * definiti per l'oggetto l'operazione fallira'.*
  1159.  ************************************************/
  1160. long int GD_cattpoly(in,num,color,twoside)
  1161. REG(a0)struct ambient3d *in;
  1162. REG(d0)long int num;
  1163. REG(d1)long int color;
  1164. REG(d2)long int twoside;
  1165. {
  1166. struct objectnode *obj;
  1167. struct polygon *poly;
  1168.  
  1169. obj=pobj(in);
  1170. poly=obj->polys;
  1171.  
  1172. if (num+1>obj->numpolys) return(0);
  1173. if (num<NULL) return(0);
  1174.  
  1175. if (poly[num].numpoints>2) poly[num].twosided=twoside;
  1176. poly[num].color=color;
  1177.  
  1178. return(1);
  1179. }
  1180.  
  1181. /************************************************
  1182.  ** Setta come attuale l'oggetto di cui e'dato **
  1183.  ** l'identificativo.                   **
  1184.  ************************************************
  1185.  *** INPUT :                        * 
  1186.  * in -> valore > 0 restituito da display3d.    *
  1187.  * num -> identificativo oggetto da settare.    * 
  1188.  *** OUTPUT:                    *
  1189.  * > 0 tutto ok,                 * 
  1190.  * = 0 operazione fallita.            *
  1191.  ************************************************/
  1192. long int GD_setobj(in,num)
  1193. REG(a0)struct ambient3d *in;
  1194. REG(d0)long int num;
  1195. {
  1196. long int ris,buf;
  1197. struct objectnode *obj;
  1198.  
  1199. ris=0;
  1200. if (num==0) return(0);
  1201. buf=in->attuale;
  1202. obj=resetobj(in);
  1203. while ((obj!=0 AND ris==0))
  1204.     {
  1205.     if (num==obj->id) 
  1206.         {
  1207.         ris=1;    
  1208.         }
  1209.     else    
  1210.         {
  1211.         obj=nextobj(in);
  1212.         }
  1213.     }
  1214.  
  1215. if (ris==NULL) in->attuale=buf;
  1216. return(ris);
  1217.  
  1218. }
  1219.  
  1220. /************************************************
  1221.  ** Ritorna l'identificativo dell'oggetto      **
  1222.  ** attuale.                       **
  1223.  ************************************************
  1224.  *** INPUT :                        * 
  1225.  * in -> valore > 0 restituito da display3d.    *
  1226.  *** OUTPUT:                    *
  1227.  * >0 tutto ok, valore identificativo.        *
  1228.  * = 0 operazione fallita.            *
  1229.  ************************************************/
  1230. long int GD_getobj(in)
  1231. REG(a0)struct ambient3d *in;
  1232. {
  1233. struct objectnode *obj;
  1234.  
  1235. obj=pobj(in);
  1236.  
  1237. return(obj->id);
  1238.  
  1239. }
  1240.  
  1241. /*************************************
  1242.  ** ROUTIN PER CABIARE IL COLORE    **
  1243.  ** DI UN REGISTRO DELLA PALETTE    **
  1244.  *************************************
  1245.  **** INPUT :                **
  1246.  ** graf ->valore non 0 ritornato da**
  1247.  **        display3d.            **
  1248.  ** nr   ->numero registro da       **
  1249.  **        variare.            **
  1250.  ** red  ->livello rosso (0-15).    **
  1251.  ** green->livello verde (0-15).    **
  1252.  ** blue ->livello blu   (0-15).    **
  1253.  **** OUTPUT:                **
  1254.  ** nessuno.                **
  1255.  *************************************/
  1256. void GD_rgb4(REG(a0)struct ambient3d *in,REG(d0)long int n,
  1257.     REG(d1)long int red,REG(d2)long int green,REG(d3)long int blue) 
  1258. {
  1259. struct grafica *graf;
  1260.  
  1261. graf=in->graf;
  1262. if (((long int)graf<=NULL) OR ((long int)(graf->vpor)<=NULL)) return(0);
  1263.  
  1264. SetRGB4(graf->vpor,n,red,green,blue);
  1265. }
  1266.  
  1267. /******************************************************
  1268.  ** visualizza effettivamente i poligoni nella frame **
  1269.  ** corrente. Ordina i poligoni in base alla Z max.  **
  1270.  ******************************************************
  1271.  *** INPUT :                          * 
  1272.  * in -> valore > 0 restituito da display3d.          *
  1273.  *** OUTPUT:                          *
  1274.  * puntatore a RastPort su cui si e' disegnato.          *
  1275.  * In caso di libreria ottimizzato e' quello della    *
  1276.  * finestra di visualizzazione.                  *
  1277.  ******************************************************/
  1278. struct RastPort *GD_paintframe(in)
  1279. REG(a0)struct ambient3d *in;
  1280. {
  1281. long int it,buf;
  1282.  
  1283. it=0;
  1284.  
  1285. /** riordino tutti i poligoni in base alla loro distanza **/
  1286. /** dall'osservatore.                    **/
  1287. /** si effettua solo se il modo di visualizzazione non **/
  1288. /** e' WIREFRAME (ho usato il quicksort)           **/
  1289. if (in->view_mode!=WIREF) it=quicksort(in->total_polys,in->iwpolys);
  1290.  
  1291. buf=in->graf->rast->DrawMode;
  1292. /* ripulisco la frame attuale */
  1293. cls_f(in);
  1294.  
  1295. over(in->graf,1);
  1296.  
  1297. /** inizio la visualizzazione vera e propia della frame attuale **/
  1298. paintpol(in,in->iwpolys,in->total_polys,in->bord_col);
  1299.  
  1300. over(in->graf,buf);
  1301.  
  1302. return (in->graf->rast);
  1303. }
  1304.  
  1305. /**********************************************
  1306.  ** ri-calcola la vista del mondo 3d.        **
  1307.  **********************************************
  1308.  *** INPUT :                      * 
  1309.  * in -> valore > 0 restituito da display3d.  *
  1310.  *** OUTPUT:                      *
  1311.  * nessuno.                      *
  1312.  **********************************************/
  1313. void GD_newview(in)
  1314. REG(a0)struct ambient3d *in;
  1315. {
  1316. struct objectnode *obj;
  1317. long int buf;
  1318.  
  1319. /*
  1320. #ifdef DEBUG
  1321. char dbg[80];
  1322. #endif
  1323. */
  1324.  
  1325. createworldtocamera(in);
  1326.  
  1327. /* resetlist() */
  1328. buf=in->attuale;
  1329. obj=resetobj(in);
  1330.  
  1331. /*
  1332. #ifdef DEBUG
  1333. sprintf(dbg,"*** INIZIO RICALCOLO SCENA ***\n");
  1334. write_dbg(dbg);
  1335. #endif
  1336. */
  1337.  
  1338. do
  1339. /** non cambiare l'ordine d'esecuzione delle routin in questo loop MAI! **/
  1340.     {
  1341.     GD_recalcobj(in);
  1342.     if (obj->trasf!=NULL OR in->agg_all!=NULL)    
  1343.         {
  1344.         if (t_removeobject(in)==NULL)
  1345.             {
  1346.             localtoworld(in);
  1347.             removebackfacesandshade(in);
  1348.             worldtocamera(in);
  1349. #ifndef OPTG
  1350.             clipobject3d(in);
  1351. #endif
  1352.             }
  1353.         }
  1354. /*  reset segnalazione di trasformazioni multiple */
  1355.     obj->trasf=0;
  1356.     obj=nextobj(in);
  1357.  
  1358.     }while(obj!=NULL);
  1359.  
  1360. /*
  1361. #ifdef DEBUG
  1362. sprintf(dbg,"*** FINE RICALCOLO SCENA ***\n\n");
  1363. write_dbg(dbg);
  1364. #endif
  1365. */
  1366.  
  1367. generatepolylist(in);
  1368.  
  1369. /* resetto flag per forzare aggiornamento scena */
  1370. in->agg_all=0;
  1371.  
  1372. /* ripristino oggetto attualmente selezionato */
  1373. in->attuale=buf;
  1374.  
  1375. }
  1376.  
  1377. /************************************************
  1378.  ** aggiorna tutti i dati precalcolati dello   **
  1379.  ** oggetto attuale.                   **
  1380.  ************************************************
  1381.  *** INPUT :                        * 
  1382.  * in -> valore > 0 restituito da display3d.    *
  1383.  *** OUTPUT:                    *
  1384.  * nessuno.                    *
  1385.  *** NOTA :                    *
  1386.  * Il ricalcolo si effettua solo se l'oggetto e'*
  1387.  * stato effettivamente modificato.        *
  1388.  ************************************************/
  1389. void GD_recalcobj(in)
  1390. REG (a0)struct ambient3d *in;
  1391. {
  1392. struct objectnode *obj;
  1393.  
  1394. obj=pobj(in);
  1395.  
  1396. if (obj->trasf!=NULL OR in->agg_all!=NULL)  
  1397.     {
  1398.     if (obj->trasf & 0x01!=NULL) aggobj(in);
  1399.     }
  1400.  
  1401. }
  1402. /********** FUNZIONI 2D *************************/
  1403. /************************************
  1404.  ** FUNZIONE PER DEFINIRE UN BOX   **
  1405.  ** DI CLIP SULLA FINESTRA         **
  1406.  ************************************
  1407.  **** INPUT :               **
  1408.  ** in   -> valore >0 ritornato    **
  1409.  **         dalla funzione d'ini-  **
  1410.  **         zializzazione display3d**
  1411.  ** minx - valore minimo x box.    **
  1412.  ** miny - valore minimo y box.    **
  1413.  ** dx - larghezza box.           **
  1414.  ** dy - altezza box.           **
  1415.  **** OUTPUT:               **
  1416.  ** > 0 tutto ok valore dx.       ** 
  1417.  ** = 0 errore.               **
  1418.  **** NOTA:               **
  1419.  ** se valori in input tutti a zero**
  1420.  ** elimina l'area di clip.       **
  1421.  ************************************/
  1422. long int GD_clipbox(REG(a0)struct ambient3d *in,REG(d0)long int minx,
  1423.            REG(d1)long int miny,REG(d2)long int dx,REG(d3)long int dy)
  1424. {
  1425. long int ris;
  1426. struct Window *win;
  1427.  
  1428. ris=clipbox(in->graf,minx,miny,dx,dy);
  1429. if (ris=NULL) return(ris);
  1430.  
  1431. win=in->win;
  1432.  
  1433. in->half_screen_width=ris/2;
  1434. in->half_screen_height=dy/2;
  1435. in->minx=minx;
  1436. in->miny=miny;
  1437. in->maxx=ris;
  1438. in->maxy=dy;
  1439.  
  1440. return(ris);
  1441.  
  1442. }
  1443.  
  1444. /************************************
  1445.  ** FUNZIONE PER VISUALIZZARE LA   **
  1446.  ** RASTPORT NASCOSTA SULLA        **
  1447.  ** FINESTRA.               **
  1448.  ************************************
  1449.  **** INPUT :               **
  1450.  ** in ->   valore >0 ritornato    **
  1451.  **         dalla funzione d'ini-  **
  1452.  **         zializzazione display3d**
  1453.  **** OUTPUT:               **
  1454.  ************************************/
  1455. void GD_switch_rp(in)
  1456. REG(a0)struct ambient3d *in;
  1457. {
  1458.  
  1459. switch_rp(in->graf);
  1460.  
  1461. }
  1462.  
  1463. /*****************************************
  1464.  ** FUNZIONE PER VARIARE CARATTERISTCHE **
  1465.  ** SCENA 3D.                **
  1466.  *****************************************
  1467.  **** INPUT :                **
  1468.  ** in -> valore >0 ritornato dalla     **
  1469.  **       funzione d'inizializzazione   **
  1470.  **      display3d().            **
  1471.  ** new-> puntatore a array di strutture**
  1472.  **      tag3d con nuovi valori.    **
  1473.  **** OUTPUT:                **
  1474.  ** == 0  - nessuna variazione .        ** 
  1475.  **  > 0  - n# variazioni eseguite.     ** 
  1476.  *****************************************/
  1477. long int GD_cascene(in,new)
  1478. REG(a0)struct ambient3d *in;
  1479. REG(a1)struct tag3d *new;
  1480. {
  1481. long int ris,i,ct,ft;
  1482.  
  1483.  
  1484. ris=0;
  1485. ct=0;
  1486.  
  1487. while(new[ct].tipo!=END_T AND ct<1000)
  1488.     {
  1489.     ft=new[ct].tipo;
  1490.     i=new[ct].val;
  1491.     switch(ft)
  1492.         {
  1493.         case(CS_PROJET):
  1494.     /* cambio tipo di proiezione */
  1495.             if (i==PROSP_P OR i==PARAL_P)
  1496.                 {
  1497.                 in->projection_type=i;
  1498.                 in->agg_all=1;    
  1499.                 ris+=1;
  1500.                 }
  1501.             break;
  1502.         case(CS_ZOOM):
  1503.     /* cambio valore zoom scena */
  1504.             if (i<256*FIXV)
  1505.                 {
  1506.                 in->zoom=i;            
  1507.                 in->agg_all=1;
  1508.                 ris+=1;
  1509.                 }
  1510.  
  1511.         case(CS_VDIST):
  1512.     /* sposto distanza osservatore dal piano di proiezione */
  1513.             if (i<=in->near_z OR i<=in->far_z)
  1514.                 {
  1515.                 in->viewing_distance=i;
  1516.                 in->agg_all=1;
  1517.                 ris+=1;
  1518.                 }
  1519.             break;
  1520.  
  1521.         case(CS_NPX0):
  1522.     /* sposto X0 box scena 3d nella sua finestra */
  1523.             in->minx=i;
  1524.             clipbox(in->graf,in->minx,in->miny,
  1525.                 in->maxx,in->maxy);
  1526.             in->agg_all=1;
  1527.             ris+=1;
  1528.             break;
  1529.  
  1530.         case(CS_NPY0):
  1531.     /* sposto Y0 box scena 3d nella sua finestra */
  1532.             in->miny=i;
  1533.             clipbox(in->graf,in->minx,in->miny,
  1534.                 in->maxx,in->maxy);
  1535.             in->agg_all=1;
  1536.             ris+=1;
  1537.             break;
  1538.     
  1539.         case(CS_GCOLOR):
  1540.     /* cambio colore fondo a scena 3d */
  1541.             in->gcolor=i;
  1542.             in->agg_all=1;
  1543.             ris+=1;
  1544.             break;
  1545.             
  1546.         }
  1547.     ct+=1;
  1548.     }
  1549.  
  1550. return(ris);
  1551. }
  1552.  
  1553. /*************************************
  1554.  ** FUNZIONE PER PASSARE DA INTERO  **
  1555.  ** A FIXPOINT.                **
  1556.  *************************************
  1557.  **** INPUT :                **
  1558.  ** in -> puntatore a intero long   **
  1559.  **       con valore da convertire. **
  1560.  ** out-> puntatore a intero long   **
  1561.  **       con valore convertito.    **
  1562.  **** OUTPUT:                **
  1563.  ** ==0 -> tutto ok.            **
  1564.  ** <>0 -> errore out non modificato**
  1565.  *************************************/
  1566. long int GD_int2fix(in,out)
  1567. REG(a0)long int *in;
  1568. REG(a1)long int *out;
  1569. {
  1570. long int bf,bf1;
  1571.  
  1572. bf=in[0];
  1573.  
  1574. /* calcolo massimo valore convertibile */
  1575. bf1=0x7fffffff >> SFIXV;
  1576.  
  1577. if (bf>bf1) return (1);
  1578. if (bf<NULL AND bf<-bf1) return (2);
  1579.  
  1580. out[0]=bf << SFIXV;
  1581.  
  1582. return(0);
  1583.  
  1584.  
  1585. /*************************************
  1586.  ** FUNZIONE PER PASSARE DA SINGLE  **
  1587.  ** FLOAT A FIXPOINT.            **
  1588.  *************************************
  1589.  **** INPUT :                **
  1590.  ** in -> puntatore a single float  **
  1591.  **       con valore da convertire. **
  1592.  ** out-> puntatore a intero long   **
  1593.  **       con valore convertito.    **
  1594.  **** OUTPUT:                **
  1595.  ** ==0 -> tutto ok.            **
  1596.  ** <>0 -> errore out non modificato**
  1597.  *************************************/
  1598. long int GD_sfl2fix(in,out)
  1599. REG(a0)float *in;
  1600. REG(a1)long int *out;
  1601. {
  1602. long int max,it,frt;
  1603. float ifix;
  1604.  
  1605. it=in[0];
  1606. ifix=FIXV;
  1607.  
  1608. /* calcolo massimo valore convertibile */
  1609. max=0x7fffffff >> SFIXV;
  1610.  
  1611. if (it>=max) return (1);
  1612. if (it<NULL AND it<=-it) return (2);
  1613.  
  1614. out[0]=in[0]*ifix;
  1615.  
  1616. return(0);
  1617.  
  1618.  
  1619. }
  1620.  
  1621. /*************************************
  1622.  ** FUNZIONE PER PASSARE DA DOUBLE  **
  1623.  ** FLOAT A FIXPOINT.            **
  1624.  *************************************
  1625.  **** INPUT :                **
  1626.  ** in -> puntatore a double float  **
  1627.  **       con valore da convertire. **
  1628.  ** out-> puntatore a intero long   **
  1629.  **       con valore convertito.    **
  1630.  **** OUTPUT:                **
  1631.  ** ==0 -> tutto ok.            **
  1632.  ** <>0 -> errore out non modificato**
  1633.  *************************************/
  1634. long int GD_dfl2fix(in,out)
  1635. REG(a0)double *in;
  1636. REG(a1)long int *out;
  1637. {
  1638. long int max,it,frt;
  1639. double ifix;
  1640.  
  1641. it=in[0];
  1642. ifix=FIXV;
  1643.  
  1644. /* calcolo massimo valore convertibile */
  1645. max=0x7fffffff >> SFIXV;
  1646.  
  1647. if (it>=max) return (1);
  1648. if (it<NULL AND it<=-it) return (2);
  1649.  
  1650. out[0]=in[0]*ifix;
  1651.  
  1652. return(0);
  1653.  
  1654.  
  1655. }
  1656.  
  1657. /*************************************
  1658.  ** FUNZIONE PER PASSARE DA FIXPOINT**
  1659.  ** AD INTERO                ** 
  1660.  *************************************
  1661.  **** INPUT :                **
  1662.  ** in -> puntatore a intero long   **
  1663.  **       con valore da convertire. **
  1664.  ** out-> puntatore a intero long   **
  1665.  **       con valore convertito.    **
  1666.  **** OUTPUT:                **
  1667.  ** ==0 -> tutto ok.            **
  1668.  ** <>0 -> errore out non modificato**
  1669.  *************************************/
  1670. long int GD_fix2int(in,out)
  1671. REG(a0)long int *in;
  1672. REG(a1)long int *out;
  1673. {
  1674. long int i;
  1675.  
  1676. i=in[0];
  1677. if (i<~0L - FIXVM) i=i+FIXVM;
  1678.  
  1679. out[0]=i >> SFIXV;
  1680.  
  1681. return(0);
  1682.  
  1683. }
  1684.  
  1685. /*************************************
  1686.  ** FUNZIONE PER PASSARE DA FIXPOINT**
  1687.  ** AD SINGLE FLOAT            ** 
  1688.  *************************************
  1689.  **** INPUT :                **
  1690.  ** in -> puntatore a intero long   **
  1691.  **       con valore da convertire. **
  1692.  ** out-> puntatore a single float  **
  1693.  **       con valore convertito.    **
  1694.  **** OUTPUT:                **
  1695.  ** ==0 -> tutto ok.            **
  1696.  ** <>0 -> errore out non modificato**
  1697.  *************************************/
  1698. long int GD_fix2sfl(in,out)
  1699. REG(a0)long int *in;
  1700. REG(a1)float *out;
  1701. {
  1702. float iv,fv,ifix;
  1703.  
  1704. ifix=FIXV;
  1705. fv=in[0] & MFRAC;
  1706. iv=in[0]>>SFIXV;
  1707.  
  1708. out[0]=iv+fv/ifix;
  1709.  
  1710. return(0);
  1711.  
  1712. }
  1713.  
  1714. /*************************************
  1715.  ** FUNZIONE PER PASSARE DA FIXPOINT**
  1716.  ** AD DOUBLE FLOAT            ** 
  1717.  *************************************
  1718.  **** INPUT :                **
  1719.  ** in -> puntatore a intero long   **
  1720.  **       con valore da convertire. **
  1721.  ** out-> puntatore a double float  **
  1722.  **       con valore convertito.    **
  1723.  **** OUTPUT:                **
  1724.  ** ==0 -> tutto ok.            **
  1725.  ** <>0 -> errore out non modificato**
  1726.  *************************************/
  1727. long int GD_fix2dfl(in,out)
  1728. REG(a0)long int *in;
  1729. REG(a1)double *out;
  1730. {
  1731. double iv,fv,ifix;
  1732.  
  1733. ifix=FIXV;
  1734. fv=in[0] & MFRAC;
  1735. iv=in[0]>>SFIXV;
  1736.  
  1737. out[0]=iv+fv/ifix;
  1738.  
  1739. return(0);
  1740.  
  1741. }
  1742.  
  1743. /*************************************
  1744.  ** FUNZIONE PER CAMBIARE IL MODO   **
  1745.  ** VIDEO DI TRACCIAMENTO.          **
  1746.  *************************************
  1747.  **** INPUT :                       **
  1748.  ** in   -> valore >0 ritornato da  **
  1749.  **         display3d().            **
  1750.  ** mod  -> nuovo modo video.       **
  1751.  **** NOTA :                **
  1752.  ** valori per mod :            **
  1753.  ** 0 > JAM1 (over 2)            **
  1754.  ** 1 > JAM2 (over 0) (def.)        **
  1755.  ** 2 > COMPLEMENT (over 1)         **
  1756.  ** 4 > INVERSVID  (inverse 1)      **
  1757.  *************************************/
  1758. void GD_over(REG(a0)struct ambient3d *in,REG(d0)long int mod)
  1759. {
  1760.  
  1761. over(in->graf,mod);
  1762.  
  1763. }
  1764.  
  1765. /*************************************
  1766.  ** FUNZIONE PER CANCELLARE UN BOX  **
  1767.  ** NELLA FINESTRA .            **
  1768.  *************************************
  1769.  **** INPUT :                       **
  1770.  ** in   -> valore >0 ritornato da  **
  1771.  **         display3d().            **
  1772.  ** x0   -> coord. x punto in alto  **
  1773.  **         a sinistra box.         **
  1774.  ** y0   -> coord. y punto in alto  **
  1775.  **         a sinistra box.         **
  1776.  ** x1   -> coord. x punto in basso **
  1777.  **         a destra box.        **
  1778.  ** y1   -> coord. y punto in basso **
  1779.  **        a destra box.        **
  1780.  **** NOTA :                **
  1781.  ** usa il colore dello sfondo, e   **
  1782.  ** non influenza le altre funzioni **
  1783.  *************************************/
  1784. void GD_cls_b(REG(a0)struct ambient3d *in,REG(d0)long int x0,
  1785.     REG(d1)long int y0,REG(d2)long int x1,REG(d3)long int y1)
  1786. {
  1787. /*
  1788. cls_b(in->graf,x0,y0,x1,y1);
  1789. */
  1790. }
  1791.  
  1792. /***************** FINE ROUTIN USABILI ESTERNAMENTE ********************/
  1793.  
  1794.